package network;

import java.util.HashMap;
import java.util.Vector;
import java.util.Map;

public class Vertex {
    private int num;
    private String label;
    private double x;
    private double y;
    private double z;
    private HashMap<String, String> params;
    private int closeness;

    private Vector<Edge> edges;

    public Vertex(int num, String label, double x, double y, double z, HashMap<String, String> params) {
        this.num = num;
        this.label = label;
        this.x = x;
        this.y = y;
        this.z = z;
        this.params = params;
        edges = new Vector<Edge>();
        this.closeness = -1;
    }

    public int getCloseness() {
        if(closeness == -1) closeness = calcCloseness();
        return closeness;
    }

    public Integer getNum() {
        return num;
    }

    public void setEdge(Edge e) {
        edges.add(e);
    }

    public int getDegree() {
        return edges.size();
    }
    
    public Vector<Edge> getEdges() {
        return edges;
    }

    public String toString() {
        return "" + num + ") " + edges.size();
    }



    // The closeness for a vertex v is the sum of geodesic
    // distances to all other vertices in the graph.
    private int calcCloseness() {
        Map<Vertex,Integer> distances = new HashMap<Vertex,Integer>();
        int d = 0;
        int lastSize = 0;

        // Assign vertex v distance zero, to indicate that it is zero
        // steps away from itself, and set d <- 0.
        distances.put(this,d);


        while (lastSize != distances.size()) {
            lastSize = distances.size();

            Map<Vertex,Integer> dist = new HashMap<Vertex,Integer>(distances);
            for (Map.Entry<Vertex,Integer> vertexEntry: dist.entrySet()) {
                // For each vertex k whose assigned distance is d,
                // follow each attached edge to the vertex m at its other end and,
                Vertex k = vertexEntry.getKey();
                if (vertexEntry.getValue() == d) {
                    for (Edge e: k.getEdges()) {
                        Vertex m = e.getOtherVertex(k);

                        //  if m has not already been assigned a distance, assign it
                        // distance d + 1 and declare k to be a predecessor of m.
                        if (!distances.containsKey(m)) {
                            distances.put(m,d+1);
                        }

                        // If m has already been assigned distance d + 1,
                        // then there is no need to do this again,
                        // but k is still declared a predecessor of m.
                        // If m has already been assigned a distance <= d, no changes are to be done.
                    }

                }
            }
            //Set d <- d + 1.
            d++;
        } //Repeat from step 2 until there are no unassigned vertices left.

        int sum = 0;
        for (int dis: distances.values())
            sum += dis;
        return sum;
    }

}
